#include "PlayerModel.h"
#include "utility.h"

const char* NotTrackBone[]={
	""
};
const Ogre::String BoneNames[]=
{
	"Root","Chest",
};

PlayerModel::PlayerModel(Ogre::SceneManager *sceneMgr,AnimID BaseAnimationID/* =AnimID::ANIM_IDLE_BASE */):
	mSceneMgr(sceneMgr)
{
	this->setSpeed(5);
	bones[0].BoneName = "Waist";
	bones[1].BoneName = "Chest";
	bones[2].BoneName = "Neck";
	bones[3].BoneName = "Humerus.L";
	bones[4].BoneName = "Ulna.L";
	bones[5].BoneName = "Thigh.L";
	bones[6].BoneName = "Calf.L";
	bones[7].BoneName = "Humerus.R";
	bones[8].BoneName = "Ulna.R";
	bones[9].BoneName = "Thigh.R";
	bones[10].BoneName = "Calf.R";
	Initialization();
}

PlayerModel::~PlayerModel()
{

}

void PlayerModel::transformBone(const Ogre::String& modelBoneName, XnSkeletonJoint skelJoint, bool flip=false)
{
	// Get the model skeleton bone info
	Skeleton* skel = mBodyEnt->getSkeleton();
	Ogre::Bone* bone = skel->getBone(modelBoneName);
	Ogre::Quaternion qI = bone->getInitialOrientation();
	Ogre::Quaternion newQ = Kinect::getSingleton().getJointOrientation(skelJoint);

	if(newQ != Ogre::Quaternion::IDENTITY)
	{
		bone->resetOrientation(); //in order for the conversion from world to local to work.
		newQ = bone->convertWorldToLocalOrientation(newQ);

		bone->setOrientation(newQ*qI);	
	}
}

void PlayerModel::setBoneData()
{
	static bool bNewUser = true;
	static bool bRightAfterSwardsPositionChanged = false;
	static Ogre::Vector3 origTorsoPos;

	xn::SkeletonCapability pUserSkel = Kinect::getSingleton().m_UserGenerator.GetSkeletonCap();

	//set smoothing according to the players request.
	if(m_SmoothingDelta!=0)
	{
		m_SmoothingFactor += 0.01 * m_SmoothingDelta;
		if(m_SmoothingFactor >= 1)
			m_SmoothingFactor = 0.99;
		if(m_SmoothingFactor <= 0)
			m_SmoothingFactor = 0.00;
		pUserSkel.SetSmoothing(m_SmoothingFactor);
		Ogre::DisplayString blah = "H/N ";
		blah.append(Ogre::StringConverter::toString((Real)m_SmoothingFactor));
		//m_help->setParamValue("Smoothing", blah);
	}

	// check for start/end pose
	if (IN_POSE_FOR_LONG_TIME == Kinect::getSingleton().m_pEndPoseDetector->checkPoseDuration())
	{
		Kinect::getSingleton().m_UserGenerator.GetSkeletonCap().StopTracking(Kinect::getSingleton().m_candidateID);
		Kinect::getSingleton().m_UserGenerator.GetPoseDetectionCap().StartPoseDetection("Psi", Kinect::getSingleton().m_candidateID);
		Kinect::getSingleton().m_candidateID = 0;
		resetBonesToInitialState();
		Kinect::getSingleton().m_pEndPoseDetector->Reset();
		Kinect::getSingleton().m_pStartPoseDetector->Reset();

		// end pose OK - re-apply the quit slider
		// but make sure we're not in a session already -- nuke the session generator
		Kinect::getSingleton().m_pSessionManager->EndSession();
		Kinect::getSingleton().m_pQuitFlow->SetActive(Kinect::getSingleton().m_pQuitSSlider);

		suppress = false;
		bNewUser = true;

		return;
	}

	// We dont care about the result of this, it is a simple progress-keeping mechanism
	Kinect::getSingleton().m_pStartPoseDetector->checkPoseDuration();

	Skeleton* skel = mBodyEnt->getSkeleton();
	Ogre::Bone* rootBone = skel->getBone("Root");

	XnSkeletonJointPosition torsoPos;

	if (pUserSkel.IsTracking(Kinect::getSingleton().m_candidateID))
	{
		if(bNewUser)
		{			
			pUserSkel.GetSkeletonJointPosition(Kinect::getSingleton().m_candidateID, XN_SKEL_TORSO, torsoPos);
			if(torsoPos.fConfidence > 0.5)
			{
				origTorsoPos.x = -torsoPos.position.X;
				origTorsoPos.y = torsoPos.position.Y;
				origTorsoPos.z = -torsoPos.position.Z;
				bNewUser = false;
			}
		}

		transformBone("Stomach",XN_SKEL_TORSO, true);
		transformBone("Waist", XN_SKEL_WAIST);
		transformBone("Root", XN_SKEL_WAIST);
		transformBone("Chest",XN_SKEL_TORSO, true);
		transformBone("Humerus.L",XN_SKEL_LEFT_SHOULDER);
		transformBone("Humerus.R",XN_SKEL_RIGHT_SHOULDER);
		transformBone("Ulna.L",XN_SKEL_LEFT_ELBOW);
		transformBone("Ulna.R",XN_SKEL_RIGHT_ELBOW);
		transformBone("Thigh.L",XN_SKEL_LEFT_HIP);
		transformBone("Thigh.R",XN_SKEL_RIGHT_HIP);
		transformBone("Calf.L",XN_SKEL_LEFT_KNEE);
		transformBone("Calf.R",XN_SKEL_RIGHT_KNEE);

		if(!bNewUser)
		{			 
			pUserSkel.GetSkeletonJointPosition(Kinect::getSingleton().m_candidateID, XN_SKEL_TORSO, torsoPos);
			Ogre::Vector3 newPos;
			newPos.x = -torsoPos.position.X;
			newPos.y = torsoPos.position.Y;
			newPos.z = -torsoPos.position.Z;

			Ogre::Vector3 newPos2 = (newPos - origTorsoPos)/100;

			newPos2.y -= 0.3;

			if (newPos2.y < 0)
			{
				newPos2.y /= 2.5;

				if (newPos2.y < -1.5)
				{
					newPos2.y = -1.5;
				}
			}
			if(torsoPos.fConfidence > 0.5)
			{
				rootBone->setPosition(newPos2);
			}
		}

		//do gestures for swards
		if ((mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
		{
			XnSkeletonJointPosition headPos;
			XnSkeletonJointPosition leftHand;
			XnSkeletonJointPosition rightHand;
			pUserSkel.GetSkeletonJointPosition(Kinect::getSingleton().m_candidateID, XN_SKEL_HEAD, headPos);
			pUserSkel.GetSkeletonJointPosition(Kinect::getSingleton().m_candidateID, XN_SKEL_LEFT_HAND, leftHand);
			pUserSkel.GetSkeletonJointPosition(Kinect::getSingleton().m_candidateID, XN_SKEL_RIGHT_HAND, rightHand);
			if(leftHand.fConfidence > 0 && headPos.fConfidence > 0)
			{
				XnV3DVector leftvec = XnV3DVector(leftHand.position);
				XnV3DVector rightvec = XnV3DVector(rightHand.position);
				XnV3DVector headvec = XnV3DVector(headPos.position);
				XnV3DVector tempvec;
				tempvec = leftvec - rightvec;
				if(tempvec.MagnitudeSquared() < 50000)
				{
					tempvec = leftvec - headvec;
					if(!bRightAfterSwardsPositionChanged &&
						tempvec.MagnitudeSquared() < 100000)
					{

						if(leftHand.position.Z+150 > headPos.position.Z)
						{
							// take swords out (or put them back, since it's the same animation but reversed)
							setTopAnimation(ANIM_DRAW_SWORDS, true);
							mTimer = 0;
							bRightAfterSwardsPositionChanged = true;
						}
					}
				} else
				{
					bRightAfterSwardsPositionChanged = false;
				}
			}	
		}
	} // end if player calibrated
	else
	{
		//return to initialState
		if(!bNewUser)
		{
			rootBone->resetToInitialState();
		}
		bNewUser = true;
	}

	bones[0].first = skel->getBone("Root")->_getDerivedPosition();
	bones[0].second = skel->getBone("Chest")->_getDerivedPosition();
	bones[0].BonePosition = (bones[0].first + bones[0].second) / 2;
	bones[0].BoneOrientation = skel->getBone("Waist")->_getDerivedOrientation();
		
	bones[1].first = skel->getBone("Chest")->_getDerivedPosition();
	bones[1].second = skel->getBone("Neck")->_getDerivedPosition();
	bones[1].BonePosition = (bones[1].first + bones[1].second) / 2;
	bones[1].BoneOrientation = skel->getBone("Chest")->_getDerivedOrientation();

	bones[2].first = skel->getBone("Neck")->_getDerivedPosition();
	Ogre::Vector3 mDirection = skel->getBone("Chest")->_getDerivedOrientation() * Ogre::Vector3::UNIT_Y;
	mDirection.normalise();
	mDirection *= 0.6685;
	bones[2].BonePosition = bones[2].first + mDirection;
	bones[2].BoneOrientation = skel->getBone("Chest")->_getDerivedOrientation();

	bones[3].first = skel->getBone("Humerus.L")->_getDerivedPosition();
	bones[3].second = skel->getBone("Ulna.L")->_getDerivedPosition();
	bones[3].BonePosition = (bones[3].first + bones[3].second) / 2;
	bones[3].BoneOrientation = skel->getBone("Humerus.L")->_getDerivedOrientation();

	bones[4].first = skel->getBone("Ulna.L")->_getDerivedPosition();
	bones[4].second = skel->getBone("Hand.L")->_getDerivedPosition();
	bones[4].BonePosition = (bones[4].first + bones[4].second) / 2;
	bones[4].BoneOrientation = skel->getBone("Ulna.L")->_getDerivedOrientation();

	bones[5].first = skel->getBone("Thigh.L")->_getDerivedPosition();
	bones[5].second = skel->getBone("Calf.L")->_getDerivedPosition();
	bones[5].BonePosition = (bones[5].first + bones[5].second) / 2;
	bones[5].BoneOrientation = skel->getBone("Thigh.L")->_getDerivedOrientation();

	bones[6].first = skel->getBone("Calf.L")->_getDerivedPosition();
	bones[6].second = skel->getBone("Foot.L")->_getDerivedPosition();
	bones[6].BonePosition = (bones[6].first + bones[6].second) / 2;
	bones[6].BoneOrientation = skel->getBone("Calf.L")->_getDerivedOrientation();

	bones[7].first = skel->getBone("Humerus.R")->_getDerivedPosition();
	bones[7].second = skel->getBone("Ulna.R")->_getDerivedPosition();
	bones[7].BonePosition = (bones[7].first + bones[7].second) / 2;
	bones[7].BoneOrientation = skel->getBone("Humerus.R")->_getDerivedOrientation();

	bones[8].first = skel->getBone("Ulna.R")->_getDerivedPosition();
	bones[8].second = skel->getBone("Hand.R")->_getDerivedPosition();
	bones[8].BonePosition = (bones[8].first + bones[8].second) / 2;
	bones[8].BoneOrientation = skel->getBone("Ulna.R")->_getDerivedOrientation();

	bones[9].first = skel->getBone("Thigh.R")->_getDerivedPosition();
	bones[9].second = skel->getBone("Calf.R")->_getDerivedPosition();
	bones[9].BonePosition = (bones[9].first + bones[9].second) / 2;
	bones[9].BoneOrientation = skel->getBone("Thigh.R")->_getDerivedOrientation();

	bones[10].first = skel->getBone("Calf.R")->_getDerivedPosition();
	bones[10].second = skel->getBone("Foot.R")->_getDerivedPosition();
	bones[10].BonePosition = (bones[10].first + bones[10].second) / 2;
	bones[10].BoneOrientation = skel->getBone("Calf.R")->_getDerivedOrientation();

//		Ogre::Vector3 v3 = bones[1].BoneOrientation * Ogre::Vector3::UNIT_Z;
	for(int i = 0; i < 11; i++)
	{
		bones[i].BoneVector = bones[i].BonePosition - bones[i].first;
	}	
}

BoneData* PlayerModel::getBoneData()
{
	return bones;
}

void PlayerModel::setJumpAnimation()
{
	setBaseAnimation(ANIM_JUMP_START, true);
	setTopAnimation(ANIM_NONE);
	mTimer = 0;
}

void PlayerModel::setTopAnimation( AnimID id,bool strictReset)
{
	if(id==mTopAnimID) return;
	if (mTopAnimID >= 0 && mTopAnimID < NUM_ANIMS)
	{
		// if we have an old animation, fade it out
		mAnims[mTopAnimID]->setEnabled(false);
	}

	mTopAnimID = id;

	if (id != ANIM_NONE)
	{
		// if we have a new animation, enable it and fade it in
		mAnims[id]->setEnabled(true);
		//mAnims[id]->setWeight(0);
		//mFadingOut[id] = false;
		//mFadingIn[id] = true;
		if (strictReset) mAnims[id]->setTimePosition(0);
	}
}

PlayerModel::AnimID PlayerModel::getTopAnimation()
{
	return this->mTopAnimID;
}

void PlayerModel::setBaseAnimation( AnimID id,bool strictReset)
{
	if(id==mBaseAnimID) return;
	if (mBaseAnimID >= 0 && mBaseAnimID < NUM_ANIMS)
		mAnims[mBaseAnimID]->setEnabled(false);
	//{
	//	// if we have an old animation, fade it out
	//	mFadingIn[mBaseAnimID] = false;
	//	mFadingOut[mBaseAnimID] = true;
	//}

	mBaseAnimID = id;

	if (id != ANIM_NONE)
	{
		// if we have a new animation, enable it and fade it in
		mAnims[id]->setEnabled(true);
		//mAnims[id]->setWeight(0);
		//mFadingOut[id] = false;
		//mFadingIn[id] = true;
		if (strictReset) mAnims[id]->setTimePosition(0);
	}
}

PlayerModel::AnimID PlayerModel::getBaseAnimation()
{
	return this->mBaseAnimID;
}

void PlayerModel::setBoneAnimationEnable( Ogre::String BoneNames[],bool state,int size )
{
	int BoneCnt = size;
	Ogre::SkeletonInstance* skeleton = this->mBodyEnt->getSkeleton();
	for(int j =0;j<BoneCnt;j++)
	{
		skeleton->getBone(BoneNames[j])->setInheritOrientation(false);
		for (int i=0;i<NUM_ANIMS;i++)
		{
			Animation* anni = skeleton->getAnimation(this->mAnims[i]->getAnimationName());
			if(!state)
			{
				skeleton->getBone(BoneNames[j])->setManuallyControlled(true);
				anni->destroyNodeTrack(skeleton->getBone(BoneNames[j])->getHandle());
			}
			else
			{
				skeleton->getBone(BoneNames[j])->setManuallyControlled(false);
				anni->createNodeTrack(skeleton->getBone(BoneNames[j])->getHandle());
			}
		}
	}
}

void PlayerModel::AddTime( Ogre::Real deltaTime )
{
	PapaObject::AddTime(deltaTime);
	if(IsMoving()) 
	{
		this->setBaseAnimation(ANIM_RUN_BASE);
		this->setTopAnimation(ANIM_RUN_TOP);
	}
	else
	{
		this->setBaseAnimation(ANIM_IDLE_BASE);
		this->setTopAnimation(ANIM_IDLE_TOP);
	}
	updateAnimations(deltaTime);
}

void PlayerModel::updateAnimations(Real deltaTime)
{
	Real baseAnimSpeed = 1;
	Real topAnimSpeed = 1;

	mTimer += deltaTime;

	if (mTopAnimID == ANIM_DRAW_SWORDS)
	{
		// flip the draw swords animation if we need to put it back
		topAnimSpeed = mSwordsDrawn ? -1 : 1;

		// half-way through the animation is when the hand grasps the handles...
		if (mTimer >= mAnims[mTopAnimID]->getLength() / 2 &&
			mTimer - deltaTime < mAnims[mTopAnimID]->getLength() / 2)
		{
			// so transfer the swords from the sheaths to the hands
			mBodyEnt->detachAllObjectsFromBone();
			mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.L" : "Handle.L", mSword1);
			mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.R" : "Handle.R", mSword2);
			// change the hand state to grab or let go
			mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
			mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);

			// toggle sword trails
			if (mSwordsDrawn)
			{
				mSwordTrail->setVisible(false);
				mSwordTrail->removeNode(mSword1->getParentNode());
				mSwordTrail->removeNode(mSword2->getParentNode());
			}
			else
			{
				mSwordTrail->setVisible(true);
				mSwordTrail->addNode(mSword1->getParentNode());
				mSwordTrail->addNode(mSword2->getParentNode());
			}
		}

		if (mTimer >= mAnims[mTopAnimID]->getLength())
		{
			// animation is finished, so return to what we were doing before
			if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
			else
			{
				setTopAnimation(ANIM_RUN_TOP);
				mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
			}
			mSwordsDrawn = !mSwordsDrawn;
		}
	}
	else if (mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
	{
		if (mTimer >= mAnims[mTopAnimID]->getLength())
		{
			// animation is finished, so return to what we were doing before
			if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
			else
			{
				setTopAnimation(ANIM_RUN_TOP);
				mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
			}
		}

		// don't sway hips from side to side when slicing. that's just embarrasing.
		if (mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed = 0;
	}
	else if (mBaseAnimID == ANIM_JUMP_START)
	{
		if (mTimer >= mAnims[mBaseAnimID]->getLength())
		{
			// takeoff animation finished, so time to leave the ground!
			setBaseAnimation(ANIM_JUMP_LOOP, true);
			// apply a jump acceleration to the character
			//mVerticalVelocity = JUMP_ACCEL;
		}
	}
	else if (mBaseAnimID == ANIM_JUMP_END)
	{
		if (mTimer >= mAnims[mBaseAnimID]->getLength())
		{
			// safely landed, so go back to running or idling
			if (!IsMoving())
			{
				setBaseAnimation(ANIM_IDLE_BASE);
				setTopAnimation(ANIM_IDLE_TOP);
			}
			else
			{
				setBaseAnimation(ANIM_RUN_BASE, true);
				setTopAnimation(ANIM_RUN_TOP, true);
			}
		}
	}

	// increment the current base and top animation times
	if (mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
	if (mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);

	// apply smooth transitioning between our animations
	//fadeAnimations(deltaTime);
}

void PlayerModel::fadeAnimations( Real deltaTime )
{
	for (int i = 0; i < NUM_ANIMS; i++)
	{
		if (mFadingIn[i])
		{
			// slowly fade this animation in until it has full weight
			Real newWeight = mAnims[i]->getWeight() + deltaTime * ANIM_FADE_SPEED;
			mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
			if (newWeight >= 1) mFadingIn[i] = false;
		}
		else if (mFadingOut[i])
		{
			// slowly fade this animation out until it has no weight, and then disable it
			Real newWeight = mAnims[i]->getWeight() - deltaTime * ANIM_FADE_SPEED;
			mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
			if (newWeight <= 0)
			{
				mAnims[i]->setEnabled(false);
				mFadingOut[i] = false;
			}
		}
	}
}

void PlayerModel::Initialization()
{

	#pragma region Initial Model
// create main model
	mBodyNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3::UNIT_Y * CHAR_HEIGHT);
	mAttachedSceneNode = mBodyNode;
	mBodyEnt = mSceneMgr->createEntity("SinbadBody", "Sinbad.mesh");
	mBodyNode->attachObject(mBodyEnt);

	// create swords and attach to sheath
	mSword1 = mSceneMgr->createEntity("SinbadSword1", "Sword.mesh");
	mSword2 = mSceneMgr->createEntity("SinbadSword2", "Sword.mesh");
	mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
	mBodyEnt->attachObjectToBone("Sheath.R", mSword2);

	// create a couple of ribbon trails for the swords, just for fun
	NameValuePairList params;
	params["numberOfChains"] = "2";
	params["maxElements"] = "80";
	mSwordTrail = (RibbonTrail*)mSceneMgr->createMovableObject("RibbonTrail", &params);
	mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
	mSwordTrail->setTrailLength(20);
	mSwordTrail->setVisible(false);
	mSceneMgr->getRootSceneNode()->attachObject(mSwordTrail);


	for (int i = 0; i < 2; i++)
	{
		mSwordTrail->setInitialColour(i, 1, 0.8, 0);
		mSwordTrail->setColourChange(i, 0.75, 1.25, 1.25, 1.25);
		mSwordTrail->setWidthChange(i, 1);
		mSwordTrail->setInitialWidth(i, 0.5);
	}
#pragma endregion Initial Model


	#pragma region Initial bone data
	for(int bone_cnt=0;bone_cnt<mBodyEnt->getSkeleton()->getNumBones();bone_cnt++)
	{
		_keyOrientation[mBodyEnt->getSkeleton()->getBone(bone_cnt)->getName()]=mBodyEnt->getSkeleton()->getBone(bone_cnt)->getInitialOrientation();
	}
	_kinectOrientation = _keyOrientation;
	Ogre::Quaternion q = Quaternion::IDENTITY;
	Quaternion q2,q3;
	Ogre::Vector3 xAxis,yAxis,zAxis;
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,-1));
	q.ToAxes(xAxis,yAxis,zAxis);
	q2.FromAngleAxis(Ogre::Degree(90),xAxis);
	_kinectOrientation["Humerus.L"]=q*q2;
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,1));
	q.ToAxes(xAxis,yAxis,zAxis);
	q2.FromAngleAxis(Ogre::Degree(90),xAxis);
	_kinectOrientation["Humerus.R"]=q*q2;
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,-1));	 
	q2.FromAngleAxis(Ogre::Degree(45),Ogre::Vector3(0,-1,0));
	_kinectOrientation["Ulna.L"]=q*q2;
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,1));	 
	_kinectOrientation["Ulna.R"]=q*q2.Inverse();

	q.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(0,1,0));
	_kinectOrientation["Chest"]=q;
	_kinectOrientation["Stomach"]=q;
	q.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(1,0,0));	 	
	q2.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(0,1,0));
	_kinectOrientation["Thigh.L"]=q*q2;
	_kinectOrientation["Thigh.R"]=q*q2;
	_kinectOrientation["Calf.L"]=q*q2;
	_kinectOrientation["Calf.R"]=q*q2;
	setupBone("Root",Degree(0),Degree(0),Degree(0));
	#pragma endregion Initial bone data


	#pragma region initial animations
	mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);
	String animNames[] =
	{"IdleBase", "IdleTop", "RunBase", "RunTop", "HandsClosed", "HandsRelaxed", "DrawSwords",
	"SliceVertical", "SliceHorizontal", "Dance", "JumpStart", "JumpLoop", "JumpEnd"};

	// populate our animation list
	for (int i = 0; i < NUM_ANIMS; i++)
	{
		mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
		mAnims[i]->setLoop(true);
		mFadingIn[i] = false;
		mFadingOut[i] = false;
	}

	// start off in the idle state (top and bottom together)
	setBaseAnimation(ANIM_IDLE_BASE);
	setTopAnimation(ANIM_IDLE_TOP);

	// relax the hands since we're not holding anything
	mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
	#pragma endregion initial animations

	/*#pragma region initial bone
	mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);

	Ogre::Quaternion q = Quaternion::IDENTITY;
	Quaternion q2,q3;
	Ogre::Vector3 xAxis,yAxis,zAxis;
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,-1));
	q.ToAxes(xAxis,yAxis,zAxis);
	q2.FromAngleAxis(Ogre::Degree(90),xAxis);
	setupBone("Humerus.L",q*q2);
	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,1));
	q.ToAxes(xAxis,yAxis,zAxis);
	q2.FromAngleAxis(Ogre::Degree(90),xAxis);
	setupBone("Humerus.R",q*q2);

	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,-1));	 
	q2.FromAngleAxis(Ogre::Degree(45),Ogre::Vector3(0,-1,0));

	setupBone("Ulna.L",q*q2);

	q.FromAngleAxis(Ogre::Degree(90),Ogre::Vector3(0,0,1));	 	
	setupBone("Ulna.R",q*q2.Inverse());

	q.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(0,1,0));
	setupBone("Chest",q);
	setupBone("Stomach",q);
	q.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(1,0,0));	 	
	q2.FromAngleAxis(Ogre::Degree(180),Ogre::Vector3(0,1,0));
	setupBone("Thigh.L",q*q2);
	setupBone("Thigh.R",q*q2);
	setupBone("Calf.L",q*q2);
	setupBone("Calf.R",q*q2);
	setupBone("Root",Degree(0),Degree(0),Degree(0));
	#pragma endregion initial bone*/

}


void PlayerModel::setupBone( const String& name,const Ogre::Quaternion& q )
{
	Ogre::Bone* bone = mBodyEnt->getSkeleton()->getBone(name);
	//bone->setManuallyControlled(true);
	bone->setInheritOrientation(false);

	bone->resetOrientation();
	bone->setOrientation(q);

	bone->setInitialState();
}
void PlayerModel::setupBone( const String& name,const Ogre::Radian& angle, const Ogre::Vector3 axis )
{

	Quaternion q;
	q.FromAngleAxis(angle,axis);	 
	setupBone(name, q);

}
void PlayerModel::setupBone( const String& name,const Degree& yaw,const Degree& pitch,const Degree& roll )
{
	Ogre::Bone* bone = mBodyEnt->getSkeleton()->getBone(name);
	//bone->setManuallyControlled(true);
	bone->setInheritOrientation(false);

	bone->resetOrientation();

	bone->yaw(yaw);
	bone->pitch(pitch);
	bone->roll(roll);

	//Matrix3 mat = bone->getLocalAxes();
	bone->setInitialState();

}

void PlayerModel::setupBone( std::map<Ogre::String,Ogre::Quaternion>& initial )
{
	std::map<Ogre::String,Ogre::Quaternion>::iterator iter;
	for(iter=initial.begin();iter!=initial.end();iter++)
	{
		Ogre::Bone*bone = mBodyEnt->getSkeleton()->getBone(iter->first);
		bone->resetToInitialState();
		bone->resetOrientation();
		bone->setOrientation(iter->second);
		bone->setInitialState();
	}
}

void PlayerModel::setBoneDataMode( int i )
{
	Ogre::String ignorBoneArray[] = {"Ulna.L","Ulna.R",
		"Humerus.L","Humerus.R",
		"Stomach","Chest",
		"Thigh.L","Thigh.R",
		"Calf.L","Calf.R",
		"Root"};
	if(i==BONE_ANMI)
	{
		setupBone(_keyOrientation);
		this->setBoneAnimationEnable(ignorBoneArray,true,sizeof(ignorBoneArray)/sizeof(Ogre::String));
	}
	else if(i==BONE_KINECT)
	{
		setupBone(_kinectOrientation);
		this->setBoneAnimationEnable(ignorBoneArray,false,sizeof(ignorBoneArray)/sizeof(Ogre::String));
	}
}

void PlayerModel::resetBonesToInitialState()
{
	Skeleton* skel = mBodyEnt->getSkeleton();
	skel->getBone("Ulna.L")->resetToInitialState();
	skel->getBone("Ulna.R")->resetToInitialState();
	skel->getBone("Humerus.L")->resetToInitialState();
	skel->getBone("Humerus.R")->resetToInitialState();
	skel->getBone("Stomach")->resetToInitialState();
	skel->getBone("Chest")->resetToInitialState();
	skel->getBone("Thigh.L")->resetToInitialState();
	skel->getBone("Thigh.R")->resetToInitialState();
	skel->getBone("Calf.L")->resetToInitialState();
	skel->getBone("Calf.R")->resetToInitialState();
	skel->getBone("Root")->resetToInitialState();
}